package com.devops.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSProjectMapper;
import com.devops.admin.mapper.DOSProjectVersionMapper;
import com.devops.admin.model.*;
import com.devops.admin.po.DOSProjectVersionPhaseListPo;
import com.devops.admin.po.DOSProjectVersionPhasePo;
import com.devops.admin.service.*;
import com.devops.admin.temporal.workflow.DOSProjectVersionTimeOutWorkflow;
import com.devops.admin.util.Assert;
import com.devops.admin.util.ThreadPoolSingleton;
import com.devops.admin.vo.DOSPageVo;
import com.devops.admin.vo.DOSProjectVersionReleaseRecordVo;
import com.devops.admin.vo.DOSUpdateProjectVo;
import com.devops.admin.vo.DOSVersionOperationVo;
import com.devops.common.exception.MvcBusinessException;
import com.devops.constant.DOSEnvTypeEnum;
import com.devops.constant.DevOpsConstant;
import com.devops.constant.ProjectVersionPhaseEnum;
import com.devops.shiro.vm.BaseUserVM;
import com.devops.admin.event.ProjectVersionPhaseChangeEvent;
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowOptions;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @ClassName DOSProjectVersionServiceImpl
 * @Description TODO
 * @Author hepingguo
 * @Date 2022/6/17 09:40
 * @Version 1.0
 **/
@Service
@Slf4j
public class DOSProjectVersionServiceImpl extends ServiceImpl<DOSProjectVersionMapper, DOSProjectVersion> implements DOSProjectVersionService {
    @Autowired
    DOSProjectVersionOperateLogService dosProjectVersionOperateLogService;
    @Autowired
    DOSProjectVersionPhaseRelationService dosProjectVersionPhaseRelationService;
    @Autowired
    DOSProjectEnvClusterNamespaceRelationService dosProjectEnvClusterNamespaceRelationService;
    @Autowired
    DOSProjectService dosProjectService;
    @Autowired
    DOSProjectWebhookService dosProjectWebhookService;
    @Autowired
    DOSProjectMapper dosProjectMapper;
    @Autowired
    DOSProjectVersionReleaseRecordService dosProjectVersionReleaseRecordService;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    @Resource
    WorkflowClient workflowClient;

    @Override
    @Transactional
    public DOSProjectVersionPhaseListPo creatVersion(DOSVersionOperationVo operation) {
        checkProjectVersion(operation);
        //#####################校验版本创建时勾选的环境是否已配置相关集群#####################
        String[] inputEnvTypes = operation.getEnvTypes().split(",");
        List<String> inputEnvTypeList = new ArrayList<>(Arrays.asList(inputEnvTypes));
        //List<String> inputEnvTypeList2 = new ArrayList<>(Arrays.asList(inputEnvTypes));

        LambdaQueryWrapper<DOSProjectEnvClusterNamespaceRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DOSProjectEnvClusterNamespaceRelation::getProjectId, operation.getProjectId());
        List<DOSProjectEnvClusterNamespaceRelation> clusterList = dosProjectEnvClusterNamespaceRelationService.list(queryWrapper);
        List<String> envTypeList = clusterList.stream()
                .map(cluster -> cluster.getEnvType().toString()).distinct().collect(Collectors.toList());
        //新创建的版本环境类型List与集群的环境类型List做差集 如果差集为空 说明新建版本的环境类型都配置了集群
        inputEnvTypeList.removeAll(envTypeList);
        Assert.isTrue(inputEnvTypeList.size() == 0, "请检查项目的集群配置！");

        //#####################校验项目版本是否重复创建 同一个项目 同一个版本号 同一个环境不能重复创建#####################
        LambdaQueryWrapper<DOSProjectVersion> versionWrapper = new LambdaQueryWrapper<>();
        versionWrapper.eq(DOSProjectVersion::getProjectId, operation.getProjectId())
                .eq(DOSProjectVersion::getVersionCode, operation.getVersionCode());
        //注意这里是List 也就是数据库里可能存在同一个项目 同一个版本 不同环境的多条记录 比如 一个版本的uat 同一个版本的pro 这就是两条记录
        List<DOSProjectVersion> versionList = this.list(versionWrapper);
        Assert.isTrueMvc(CollectionUtil.isEmpty(versionList), "已存在此版本号，请更换！");

        //######################数据处理######################
        DOSProjectVersion projectVersion = new DOSProjectVersion();
        BeanUtil.copyProperties(operation, projectVersion);

        //####################创建新版本逻辑######################
        operation.setOperationType(DevOpsConstant.ProjectVersionOperateActionType.CREATE);
        Integer versionId = this.switchProjectVersionStatus(operation, projectVersion);
        operation.setVersionId(versionId);
        // 同步更新项目表的更新时间
        dosProjectService.updateById(DOSProject.builder().id(operation.getProjectId()).build());

        saveProjectReleaseRecord(operation.getProjectId(), versionId, DevOpsConstant.RRECORD_STATUS.OLD, operation.getEnvTypes(), operation.getVersionCode());
        //####################返回数据 包含项目信息 版本信息 所有阶段状态信息#######################
        return dealProjectVersionPhaseListPoInfo(operation);
    }

    private void saveProjectReleaseRecord(Integer operation, Integer versionId, int recordStatus, String envType, String versionCode) {
        DOSProjectVersionReleaseRecordVo releaseRecordVo = DOSProjectVersionReleaseRecordVo.builder()
                .projectId(operation)
                .versionId(versionId)
                .recordStatus(recordStatus)
                .envType(envType)
                .versionCode(versionCode)
                .build();
        dosProjectVersionReleaseRecordService.saveRecord(releaseRecordVo);
    }

    /**
     * 版本创建 测试完成 审核通过 审核拒绝 用户确认 发布完成 六个逻辑都需要调用此方法
     * 处理返回项目的某个版本的项目信息、版本信息、以及所有阶段状态信息
     *
     * @param operation
     * @return
     */
    @Override
    public DOSProjectVersionPhaseListPo dealProjectVersionPhaseListPoInfo(DOSVersionOperationVo operation) {
        List<DOSProjectVersionPhasePo> projectVersionPhasePoList = baseMapper.getProjectVersionPhaseList(operation.getVersionId());
        if (projectVersionPhasePoList.size() > 0) {
            AtomicBoolean bool = new AtomicBoolean(false);
            DOSProjectVersionPhasePo projectVersionPhasePoFirst = projectVersionPhasePoList.get(0);
            DOSProjectVersionPhaseListPo projectVersionPhaseListPo
                    = BeanUtil.copyProperties(projectVersionPhasePoFirst, DOSProjectVersionPhaseListPo.class);
            List<DOSProjectVersionPhaseRelation> projectVersionPhaseRelations = new ArrayList<>();
            projectVersionPhasePoList.forEach(projectVersionPhasePo -> {
                DOSProjectVersionPhaseRelation projectVersionPhaseRelation = DOSProjectVersionPhaseRelation.builder()
                        .phaseType(projectVersionPhasePo.getPhaseType())
                        .phaseName(projectVersionPhasePo.getPhaseName())
                        .phaseStatusType(projectVersionPhasePo.getPhaseStatusType())
                        .phaseStatusName(projectVersionPhasePo.getPhaseStatusName())
                        .currentFlag(projectVersionPhasePo.getCurrentFlag())
                        .build();
                if (projectVersionPhasePo.getPhaseType().intValue()
                        == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT.intValue()) {
                    bool.set(true);
                }
                projectVersionPhaseRelations.add(projectVersionPhaseRelation);
            });
            projectVersionPhaseListPo.setPhaseRelations(projectVersionPhaseRelations);
            if (bool.get()) {
                // 获取审核拒绝的拒绝信息
                DOSProjectVersionOperateLog operationLog = getOperationLog(projectVersionPhaseListPo.getVersionId());
                if (operationLog != null) {
                    projectVersionPhaseListPo.setOperateMsg(operationLog.getOperateMsg());
                }
            }
            return projectVersionPhaseListPo;
        }
        return null;
    }

    @Override
    public TableResult<DOSProjectVersionPhasePo> dealProjectVersionPhasePoInfo(DOSVersionOperationVo operation, DOSPageVo pageVo) {
        Assert.isTrue(operation != null && operation.getProjectId() != null && operation.getProjectId() > 0, "ProjectId不能为空");
        Integer projectId = operation.getProjectId();
        Page<DOSProjectVersionPhasePo> page = new Page(pageVo.getPageNum(), pageVo.getPageSize());
        TableResult<DOSProjectVersionPhasePo> tableResult = new TableResult<>();
        List<DOSProjectVersionPhasePo> projectVersionList = baseMapper.getProjectVersionList(projectId, operation.getPhaseType(), page);
        List<Integer> versionIds = projectVersionList.stream().map(DOSProjectVersionPhasePo::getVersionId).collect(Collectors.toList());
        if (versionIds.isEmpty()) {
            return tableResult;
        }
        List<DOSProjectVersionOperateLog> operateLogs = dosProjectVersionOperateLogService.list(Wrappers.<DOSProjectVersionOperateLog>lambdaQuery()
                .in(DOSProjectVersionOperateLog::getVersionId,versionIds)
                .eq(DOSProjectVersionOperateLog::getLogType, DevOpsConstant.ProjectVersionOperateLogType.ACTION_TYPE));
        Map<Integer, List<DOSProjectVersionOperateLog>> operateLogsMap = operateLogs.stream().collect(Collectors.groupingBy(DOSProjectVersionOperateLog::getVersionId));
        projectVersionList.forEach(version -> {
            String envTypes = version.getEnvTypes();
            StringBuilder envTypeNames = new StringBuilder();
            for (String envType : envTypes.split(",")) {
                envTypeNames.append(DOSEnvTypeEnum.getValueByType(Integer.valueOf(envType))).append(",");
            }
            version.setEnvTypeNames(envTypeNames.substring(0, envTypeNames.length() - 1));
            List<DOSProjectVersionOperateLog> versionOperateLogs = operateLogsMap.get(version.getVersionId());
            if (CollectionUtil.isNotEmpty(versionOperateLogs)){
                Map<Integer, List<DOSProjectVersionOperateLog>> logMaps = versionOperateLogs.stream().collect(Collectors.groupingBy(DOSProjectVersionOperateLog::getActionType));
                // 版本发布人名称
                List<DOSProjectVersionOperateLog> publisherLogs = logMaps.get(DevOpsConstant.ProjectVersionOperateActionType.CREATE);
                if (CollectionUtil.isNotEmpty(publisherLogs)){
                    DOSProjectVersionOperateLog firstAcceptLog = publisherLogs.get(0);
                    version.setPublisherName(firstAcceptLog.getOperateUserName());
                }
                // 版本申请人员
                DOSProjectVersionOperateLog applicationLog = dosProjectVersionOperateLogService.getOne(Wrappers.<DOSProjectVersionOperateLog>lambdaQuery()
                        .eq(DOSProjectVersionOperateLog::getPhaseStatusType, DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT)
                        .eq(DOSProjectVersionOperateLog::getLogType, DevOpsConstant.ProjectVersionOperateLogType.STATUS_TYPE)
                        .eq(DOSProjectVersionOperateLog::getVersionId, version.getVersionId()));
                if (applicationLog != null && applicationLog.getId() > 0){
                    version.setApplicantName(applicationLog.getOperateUserName());
                }
                // 版本审核人员
                List<DOSProjectVersionOperateLog> acceptLogList = logMaps.get(DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT);
                List<DOSProjectVersionOperateLog> webhookAcceptLogList = logMaps.get(DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT);
                List<DOSProjectVersionOperateLog> dealLogList = new ArrayList<>();

                if (CollectionUtil.isNotEmpty(acceptLogList)) {
                    dealLogList.addAll(acceptLogList);
                }
                if (CollectionUtil.isNotEmpty(webhookAcceptLogList)) {
                    dealLogList.addAll(webhookAcceptLogList);
                }
                if (CollectionUtil.isNotEmpty(dealLogList)) {
                    DOSProjectVersionOperateLog firstAcceptLog = dealLogList.get(0);
                    if (firstAcceptLog.getId() != null && StrUtil.isNotBlank(firstAcceptLog.getOperateUserName())) {
                        version.setReviewerName(firstAcceptLog.getOperateUserName());
                    }
                }
            }
        });
        Pagination p = Pagination.builder().pageNum(page.getCurrent()).pageSize(page.getSize()).total(page.getTotal()).build();
        tableResult.setList(projectVersionList);
        tableResult.setPagination(p);
        return tableResult;
    }

    @Override
    @Transactional
    public DOSProjectVersionPhaseListPo processOperation(DOSVersionOperationVo operation) {
        Assert.isTrue(operation != null, "参数不能为空");
        Assert.isTrue(operation.getVersionId() != null && operation.getVersionId() > 0, "版本id不能为空");
        Assert.isTrueMvc(operation.getOperationType() != null && operation.getOperationType() > 0, "流程操作类型不能为空");
        if (operation.getOperationType().intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT
                || operation.getOperationType().intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_REJECT) {
            Assert.isTrue(StrUtil.isNotBlank(operation.getOperateMsg()), "审核拒绝理由不能为空");
        }
        DOSProjectVersion projectVersion = new DOSProjectVersion();
        BeanUtil.copyProperties(operation, projectVersion);
        //####################核心逻辑#######################
        this.switchProjectVersionStatus(operation, projectVersion);
        if (operation.getOperationType().intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT
                || operation.getOperationType().intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT) {
            CompletableFuture.runAsync(() -> checkTimeOutProjectVersion(operation.getVersionId()));
        }
        //####################返回数据 包含项目信息 版本信息 所有阶段状态信息#######################
        return dealProjectVersionPhaseListPoInfo(operation);
    }

    /**
     * @return void
     * @Author heyabo
     * @Description 修改项目的最新的版本号
     * @Date 14:40 2022/6/27
     * @Param [operation, versionPhase]
     **/
    private void updateProjectLastVersion(DOSProjectVersionPhaseListPo versionPhase) {
        DOSUpdateProjectVo project = new DOSUpdateProjectVo();
        String envType = versionPhase.getEnvTypes();
        String[] envTypes = envType.split(",");
        StringBuilder env = new StringBuilder("(");
        for (String type : envTypes) {
            env.append(DOSEnvTypeEnum.getValueByType(Integer.valueOf(type))).append(",");
        }
        String typeEnv = env.substring(0, env.length() - 1) + ")";
        project.setLatestVersion(versionPhase.getVersionCode() + typeEnv);
        project.setId(versionPhase.getProjectId());
        dosProjectService.updateProject(project);
    }

    @Override
    public TableResult<DOSProjectVersionPhasePo> getToBeReviewed(DOSVersionOperationVo operation, DOSPageVo pageVo) {
        Page<DOSProjectVersionPhasePo> page = new Page<>();
        TableResult<DOSProjectVersionPhasePo> tableResult = new TableResult<>();
        List<DOSProjectVersionPhasePo> versionInfos = baseMapper.selectToReview(operation, page);
        Pagination p = Pagination.builder().pageNum(page.getCurrent()).pageSize(page.getSize()).total(page.getTotal()).build();
        tableResult.setList(versionInfos);
        tableResult.setPagination(p);
        return tableResult;
    }

    /**
     * @param vo                操作信息
     * @param dosProjectVersion 版本信息
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Integer switchProjectVersionStatus(DOSVersionOperationVo vo, DOSProjectVersion dosProjectVersion) {
        Integer versionId = vo.getVersionId();
        Integer operateAction = vo.getOperationType();
        String operateMsg = vo.getOperateMsg();
        int operateSourceType = vo.getOperateSourceType() != null ? vo.getOperateSourceType() : DevOpsConstant.ProjectVersionOperateSourceType.WEB_TYPE;
        //校验开始
        Assert.isTrue(operateAction != null && operateAction > 0, "操作动作类型不能为空");
        BaseUserVM user;
        if (operateSourceType == DevOpsConstant.ProjectVersionOperateSourceType.DING_TYPE) {
            //钉钉操作
            user = new BaseUserVM();
            user.setId(StrUtil.isNotBlank(vo.getOperateUserId()) ? vo.getOperateUserId() : "dingding");
            user.setRealName(StrUtil.isNotBlank(vo.getOperateUserName()) ? vo.getOperateUserName() : "钉钉");
        } else if (operateSourceType == DevOpsConstant.ProjectVersionOperateSourceType.WEB_TYPE) {
            //WEB页面操作校验
            user = (BaseUserVM) SecurityUtils.getSubject().getPrincipal();
        } else {
            user = new BaseUserVM();
            user.setId(StrUtil.isNotBlank(vo.getOperateUserId()) ? vo.getOperateUserId() : "system");
            user.setRealName(StrUtil.isNotBlank(vo.getOperateUserName()) ? vo.getOperateUserName() : "系统");
        }
        Assert.isTrue(user != null, "请先登录！");

        //新建版本
        if (versionId == null && dosProjectVersion != null && operateAction == DevOpsConstant.ProjectVersionOperateActionType.CREATE.intValue()) {
            //#####################创建新版本逻辑#######################
            //插入一条新纪录
            baseMapper.insert(dosProjectVersion);
            versionId = dosProjectVersion.getId();
            //#####################版本流程相关逻辑#####################
            //初始化版本流程
            List<DOSProjectVersionPhaseRelation> versionPhaseList = new ArrayList<>();
            //1-创建新版本 创建完成
            DOSProjectVersionPhaseRelation versionCreatePhase = DOSProjectVersionPhaseRelation.builder()
                    .versionId(versionId)
                    .phaseType(DevOpsConstant.ProjectVersionPhaseType.VERSION_CREATE)
                    .phaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.VERSION_CREATE_SUCCESS)
                    .currentFlag(0)
                    .build();
            versionPhaseList.add(versionCreatePhase);
            //2-UAT测试 测试中
            DOSProjectVersionPhaseRelation uatTestPhase = DOSProjectVersionPhaseRelation.builder()
                    .versionId(versionId)
                    .phaseType(DevOpsConstant.ProjectVersionPhaseType.UAT_TEST)
                    .build();

            //3-QA审核
            DOSProjectVersionPhaseRelation qaReviewPhase = DOSProjectVersionPhaseRelation.builder()
                    .versionId(versionId)
                    .phaseType(DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW)
                    .build();
            //4-PRO发布
            DOSProjectVersionPhaseRelation proPublishPhase = DOSProjectVersionPhaseRelation.builder()
                    .versionId(versionId)
                    .phaseType(DevOpsConstant.ProjectVersionPhaseType.PRO_PUBLISH)
                    .build();
            //5-结束
            DOSProjectVersionPhaseRelation endPhase = DOSProjectVersionPhaseRelation.builder()
                    .versionId(versionId)
                    .phaseType(DevOpsConstant.ProjectVersionPhaseType.END)
                    .build();

            String envTypes = dosProjectVersion.getEnvTypes();
            List<String> envTypesList = Arrays.asList(envTypes.split(","));
            Assert.isTrueMvc(envTypesList.size() > 0 && envTypesList.size() <= 2, "envTypes异常");
            //envType 共四种组合 "1" "1,2" "2,1" "2"
            Integer nextPhaseStatusType;
            //此版本包含UAT类型环境  即 UAT和UAT,PRO两种场景
            if (envTypesList.contains(String.valueOf(DevOpsConstant.EnvType.UAT))) {
                //envType = "1" "1,2" "2,1"
                //下一步 UAT测试阶段 UAT测试状态
                nextPhaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_ING;
                uatTestPhase.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_ING);
                uatTestPhase.setCurrentFlag(1);
                versionPhaseList.add(uatTestPhase);
                //此版本包含UAT、PRO类型环境
                if (envTypesList.contains(String.valueOf(DevOpsConstant.EnvType.PRO))) {
                    //envType = "1,2" "2,1"
                    versionPhaseList.add(qaReviewPhase);
                    versionPhaseList.add(proPublishPhase);
                }
            } else {
                //envType = "2"
                //此版本仅包含PRO类型环境
                //下一步 QA审核阶段 待审核状态
                nextPhaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT;
                qaReviewPhase.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT);
                qaReviewPhase.setCurrentFlag(1);
                versionPhaseList.add(qaReviewPhase);
                versionPhaseList.add(proPublishPhase);

            }
            versionPhaseList.add(endPhase);
            dosProjectVersionPhaseRelationService.saveBatch(versionPhaseList);

            //############################日志记录相关逻辑############################
            //插入日志记录-用户创建版本
            DOSProjectVersionOperateLog createLog = DOSProjectVersionOperateLog.builder()
                    .logType(DevOpsConstant.ProjectVersionOperateLogType.ACTION_TYPE)
                    .actionType(DevOpsConstant.ProjectVersionOperateActionType.CREATE)
                    .operateUserId(user.getId())
                    .operateUserName(user.getRealName())
                    .versionId(versionId)
                    .operateSourceType(operateSourceType)
                    .build();
            //插入日志记录-版本状态变更 创建版本成功
            DOSProjectVersionOperateLog createSuccessLog = DOSProjectVersionOperateLog.builder()
                    .logType(DevOpsConstant.ProjectVersionOperateLogType.STATUS_TYPE)
                    .phaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.VERSION_CREATE_SUCCESS)
                    .versionId(versionId)
                    .build();
            //插入日志记录-版本状态变更 开始-UAT测试中或QA审核中
            DOSProjectVersionOperateLog statusChangeLog = DOSProjectVersionOperateLog.builder()
                    .logType(DevOpsConstant.ProjectVersionOperateLogType.STATUS_TYPE)
                    .phaseStatusType(nextPhaseStatusType)
                    .versionId(versionId)
                    .build();
            if (envTypes.equals(String.valueOf(DevOpsConstant.EnvType.PRO))){
                statusChangeLog.setOperateUserId(user.getId());
                statusChangeLog.setOperateUserName(user.getRealName());
            }
            //批量插入日志
            List<DOSProjectVersionOperateLog> logList = new ArrayList<>();
            logList.add(createLog);
            logList.add(createSuccessLog);
            logList.add(statusChangeLog);
            dosProjectVersionOperateLogService.saveBatch(logList);

            //这里给管理员webhook发送信息-申请发版 20221108
            if (envTypes.equals(String.valueOf(DevOpsConstant.EnvType.PRO))) {
                applicationEventPublisher.publishEvent(new ProjectVersionPhaseChangeEvent(ProjectVersionPhaseEnum.APPLY, dosProjectVersion, user));
            }
        } else { //新建版本外的其它操作
            //################################校验以及数据处理逻辑####################################

            Assert.isTrueMvc(versionId != null && versionId > 0, "版本ID不能为空");
            dosProjectVersion = baseMapper.selectById(versionId);

            Assert.isTrueMvc(dosProjectVersion != null && dosProjectVersion.getId() != null && dosProjectVersion.getId() > 0, "版本ID错误");

            String envTypes = dosProjectVersion.getEnvTypes();

            Integer phaseStatusType = null;
            //版本流程阶段状态变更
            List<DOSProjectVersionPhaseRelation> phaseRelationList = new ArrayList<>();
            //测试完成
            if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.TEST_FINISH) {
                //当前应正处于 阶段（UAT测试 ）状态（ 测试中）
                DOSProjectVersionPhaseRelation uatTestPhaseRelation =
                        getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.UAT_TEST,
                                DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_ING, 1);
                //应更改为 1-阶段（UAT测试） 状态（ 测试完成 ） 结束此阶段
                uatTestPhaseRelation.setCurrentFlag(0);
                uatTestPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_FINISH);
                phaseRelationList.add(uatTestPhaseRelation);
                //此版本包含PRO类型环境
                if (envTypes.contains(String.valueOf(DevOpsConstant.EnvType.PRO))) {
                    //查询 阶段（QA审核）
                    DOSProjectVersionPhaseRelation qaReviewPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW, null, null);

                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT;
                    //应更改为 2-阶段（QA审核） 状态（待审核） 正处于此阶段
                    //正处于此阶段
                    qaReviewPhaseRelation.setCurrentFlag(1);
                    //状态（待审核）
                    qaReviewPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT);
                    phaseRelationList.add(qaReviewPhaseRelation);

                } else { //不包含PRO类型环境 流程可以直接结束了
                    //查询 阶段（结束）
                    DOSProjectVersionPhaseRelation endPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.END, null, null);

                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW;
                    //应更改为 2- 阶段（结束）状态（流程结束） 正处于此阶段
                    //正处于此阶段
                    endPhaseRelation.setCurrentFlag(1);
                    //状态（流程结束）
                    endPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW);
                    phaseRelationList.add(endPhaseRelation);
                    // 同步更新项目表的更新时间
                    dosProjectService.updateById(DOSProject.builder().id(vo.getProjectId()).build());
                    // 异步处理release记录
                    saveProjectReleaseRecord(vo.getProjectId(), vo.getVersionId(), DevOpsConstant.RRECORD_STATUS.NEW, vo.getEnvTypes(), vo.getVersionCode());
                }

            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT) {
                //页面点击审核通过或者WEBHOOK操作审核通过
                //检查版本QA审核阶段和对应的阶段状态
                DOSProjectVersionPhaseRelation qaReviewPhaseRelation =
                        getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW,
                                null, null);
                int phaseStatus = qaReviewPhaseRelation.getPhaseStatusType();
                int current = qaReviewPhaseRelation.getCurrentFlag();
                if (phaseStatus == DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT && current == 1) {
                    //正常场景-当前正处于QA审核阶段且阶段状态为待审核
                    //应更改为 1-阶段（QA审核） 状态（审核通过） 结束此阶段
                    //结束此阶段
                    qaReviewPhaseRelation.setCurrentFlag(0);
                    //状态（审核通过）
                    qaReviewPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_ACCEPT);
                    phaseRelationList.add(qaReviewPhaseRelation);

                    //查询 阶段（PRO发布）
                    DOSProjectVersionPhaseRelation proPublishPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.PRO_PUBLISH,
                                    null, null);
                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.PRO_PUBLISH_WAIT;
                    //应更改为 2-阶段（PRO发布） 状态（待发布） 正处于此阶段
                    proPublishPhaseRelation.setCurrentFlag(1);
                    proPublishPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.PRO_PUBLISH_WAIT);
                    phaseRelationList.add(proPublishPhaseRelation);

                } else {
                    //异常场景 - 通过点击日志判断
                    DOSProjectVersionOperateLog log = dosProjectVersionOperateLogService.getOne(Wrappers.<DOSProjectVersionOperateLog>lambdaQuery()
                            .eq(DOSProjectVersionOperateLog::getVersionId, versionId)
                            .eq(DOSProjectVersionOperateLog::getLogType, DevOpsConstant.ProjectVersionOperateLogType.ACTION_TYPE)
                            .and(item ->
                                    item.eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT)
                                            .or(i -> i.eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT))
                                            .or(i -> i.eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT))
                            ));
                    String errorMsg = "数据异常";
                    //如果有用户发布完成 和 管理员超时关闭 两种点击日志
                    if (log != null && log.getId() != null && log.getId() > 0) {
                        int actionType = log.getActionType();
                        if (actionType == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT
                                || actionType == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT) {
                            errorMsg = "该版本已被" + log.getOperateUserName() + "于" + log.getUpdateTime() + "审核通过。";
                        } else if (actionType == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT) {
                            errorMsg = "该版本已被" + log.getOperateUserName() + "于" + log.getUpdateTime() + "审核拒绝。";
                        }
                    }
                    throw new MvcBusinessException(errorMsg);
                }

            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT ||
                    operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_REJECT) {
                //审核拒绝
                //当前应正处于 阶段（QA审核） 状态（待审核）
                DOSProjectVersionPhaseRelation qaReviewPhaseRelation =
                        getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW,
                                DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT, 1);
                phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_REJECT;
                //应更改为 1-阶段（QA审核） 状态（审核拒绝）
                //状态（审核拒绝）
                qaReviewPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_REJECT);
                phaseRelationList.add(qaReviewPhaseRelation);
            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.USER_CONFIRM) {
                //用户确认
                //当前应正处于 阶段（QA审核） 状态（审核拒绝）
                DOSProjectVersionPhaseRelation qaReviewPhaseRelation =
                        getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW,
                                DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_REJECT, 1);
                //应更改为 1-阶段（QA审核）状态（审核拒绝）  结束此阶段
                qaReviewPhaseRelation.setCurrentFlag(0);
                phaseRelationList.add(qaReviewPhaseRelation);
                if (envTypes.contains(String.valueOf(DevOpsConstant.EnvType.UAT))) {
                    //包含UAT类型环境
                    //查询 阶段（UAT测试）
                    DOSProjectVersionPhaseRelation uatTestPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.UAT_TEST,
                                    null, null);

                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_ING;
                    //应更改为 2-阶段（UAT测试） 状态（测试中） 正处于此阶段
                    uatTestPhaseRelation.setCurrentFlag(1);
                    uatTestPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.UAT_TEST_ING);
                    phaseRelationList.add(uatTestPhaseRelation);
                } else { //仅PRO类型环境 流程可以结束了
                    //查询 阶段（结束）
                    DOSProjectVersionPhaseRelation endPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.END, null, null);

                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW;
                    //应更改为 2-阶段（结束） 状态（流程结束） 正处于此阶段
                    //正处于此阶段
                    endPhaseRelation.setCurrentFlag(1);
                    //状态（流程结束）
                    endPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW);
                    phaseRelationList.add(endPhaseRelation);
                    // 同步更新项目表的更新时间
                    dosProjectService.updateById(DOSProject.builder().id(vo.getProjectId()).build());
                    // 异步处理release记录
                    saveProjectReleaseRecord(vo.getProjectId(), vo.getVersionId(), DevOpsConstant.RRECORD_STATUS.NEW, vo.getEnvTypes(), vo.getVersionCode());
                }

            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.PUBLISH_FINISH
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_PUBLISH_FINISH
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.SYSTEM_FINISH) {
                //页面点击发布完成或WEBHOOK操作结束版本
                //检查版本PRO发布阶段和对应阶段状态
                DOSProjectVersionPhaseRelation proPublishPhaseRelation =
                        getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.PRO_PUBLISH,
                                null, null);
                int phaseStatus = proPublishPhaseRelation.getPhaseStatusType();
                int current = proPublishPhaseRelation.getCurrentFlag();

                if (phaseStatus == DevOpsConstant.ProjectVersionPhaseStatusType.PRO_PUBLISH_WAIT && current == 1) {
                    //正常场景 - 当前正处于PRO发布阶段且此阶段状态为待发布
                    //应更改为 1-阶段（PRO发布）  状态（发布完成） 结束此阶段
                    proPublishPhaseRelation.setCurrentFlag(0);
                    proPublishPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.PRO_PUBLISH_FINISH);
                    phaseRelationList.add(proPublishPhaseRelation);

                    //查询 阶段（结束）
                    DOSProjectVersionPhaseRelation endPhaseRelation =
                            getVersionPhaseRelation(versionId, DevOpsConstant.ProjectVersionPhaseType.END, null, null);

                    phaseStatusType = DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW;
                    //应更改为 2-阶段（结束） 状态（流程结束） 正处于此阶段
                    //正处于此阶段
                    endPhaseRelation.setCurrentFlag(1);
                    //状态（流程结束）
                    endPhaseRelation.setPhaseStatusType(DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW);
                    phaseRelationList.add(endPhaseRelation);
                    // 同步更新项目表的更新时间
                    dosProjectService.updateById(DOSProject.builder().id(vo.getProjectId()).build());

                    // 异步处理release记录
                    DOSProjectVersion version = this.getById(vo.getVersionId());
                    saveProjectReleaseRecord(version.getProjectId(), version.getId(), DevOpsConstant.RRECORD_STATUS.NEW, version.getEnvTypes(), version.getVersionCode());
                } else {
                    //异常场景 -  通过点击日志做进一步判断
                    DOSProjectVersionOperateLog log = dosProjectVersionOperateLogService.getOne(Wrappers.<DOSProjectVersionOperateLog>lambdaQuery()
                            .eq(DOSProjectVersionOperateLog::getVersionId, versionId)
                            .eq(DOSProjectVersionOperateLog::getLogType, DevOpsConstant.ProjectVersionOperateLogType.ACTION_TYPE)
                            .and(item ->
                                    item.eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_PUBLISH_FINISH)
                                            .or(i -> i.eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.PUBLISH_FINISH))));
                    String errorMsg = "数据异常";
                    //如果有用户发布完成 和 管理员超时关闭 两种点击日志
                    if (log != null && log.getId() != null && log.getId() > 0) {
                        int actionType = log.getActionType();
                        if (actionType == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_PUBLISH_FINISH
                                || actionType == DevOpsConstant.ProjectVersionOperateActionType.SYSTEM_FINISH) {
                            //管理员超时关闭
                            errorMsg = "该版本发版超时，已被" + log.getOperateUserName() + "于" + log.getUpdateTime() + "操作超时关闭。";
                        } else if (actionType == DevOpsConstant.ProjectVersionOperateActionType.PUBLISH_FINISH) {
                            errorMsg = "该版本已被" + log.getOperateUserName() + "于" + log.getUpdateTime() + "操作发布完成。";
                        }
                    }
                    throw new MvcBusinessException(errorMsg);
                }

            }
            //批量更新版本流程阶段状态
            dosProjectVersionPhaseRelationService.updateBatchById(phaseRelationList);

            //#########################日志处理相关逻辑########################
            //插入日志记录-用户操作日志
            DOSProjectVersionOperateLog operateLog = DOSProjectVersionOperateLog.builder()
                    .versionId(dosProjectVersion.getId())
                    .logType(DevOpsConstant.ProjectVersionOperateLogType.ACTION_TYPE)
                    .actionType(operateAction)
                    .operateUserId(user.getId())
                    .operateUserName(user.getRealName())
                    .operateMsg(operateMsg)
                    .operateSourceType(operateSourceType)
                    .build();

            //插入日志记录-状态变更日志
            DOSProjectVersionOperateLog statusChangeLog = DOSProjectVersionOperateLog.builder()
                    .versionId(dosProjectVersion.getId())
                    .logType(DevOpsConstant.ProjectVersionOperateLogType.STATUS_TYPE)
                    .phaseStatusType(phaseStatusType)
                    .build();

            if (phaseStatusType != null
                    && phaseStatusType.intValue() == DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_WAIT){
                statusChangeLog.setOperateUserName(user.getRealName());
                statusChangeLog.setOperateUserId(user.getId());
            }

            List<DOSProjectVersionOperateLog> logList = new ArrayList<>();
            logList.add(operateLog);
            logList.add(statusChangeLog);
            dosProjectVersionOperateLogService.saveBatch(logList);
            if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.TEST_FINISH) {
                //如果web页面点击测试完成
                if (envTypes.contains(String.valueOf(DevOpsConstant.EnvType.PRO))) {
                    applicationEventPublisher.publishEvent(new ProjectVersionPhaseChangeEvent(ProjectVersionPhaseEnum.APPLY, dosProjectVersion, user));
                }
            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_ACCEPT
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_ACCEPT) {
                //如果是webhook界面操作的 需要给管理员webhook发送消息-审核通过
                applicationEventPublisher.publishEvent(new ProjectVersionPhaseChangeEvent(ProjectVersionPhaseEnum.APPROVED, dosProjectVersion, user));
            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.PUBLISH_FINISH
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_PUBLISH_FINISH
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.SYSTEM_FINISH) {
                //如果是web页面点击发布完成 给管理员webhook发信息
                applicationEventPublisher.publishEvent(new ProjectVersionPhaseChangeEvent(ProjectVersionPhaseEnum.COMPLETED, dosProjectVersion, user));
            } else if (operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.WEBHOOK_REVIEW_REJECT
                    || operateAction.intValue() == DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT) {
                //如果是webhook界面操作的 需要给管理员webhook发送消息-审核拒绝
                applicationEventPublisher.publishEvent(new ProjectVersionPhaseChangeEvent(ProjectVersionPhaseEnum.REJECTED, dosProjectVersion, user));
            }

        }
        return versionId;
    }

    /**
     * 校验projectVersion
     *
     * @param projectVersion
     */
    public void checkProjectVersion(DOSProjectVersion projectVersion) {
        Assert.isTrue(projectVersion.getProjectId() != null && projectVersion.getProjectId() > 0, "项目ID不能为空");
        Assert.isTrue(StrUtil.isNotBlank(projectVersion.getVersionCode()), "版本号不能为空");
        Assert.isTrue(StrUtil.isNotBlank(projectVersion.getUpdateLog()), "版本更新内容不能为空");
        Assert.isTrue(StrUtil.isNotBlank(projectVersion.getEnvTypes()), "环境不能为空");
        projectVersion.setVersionCode(projectVersion.getVersionCode().trim());
    }

    /**
     * @param versionId       版本号
     * @param phaseType       阶段
     * @param phaseStatusType 阶段状态
     * @param current         是否处于当前阶段
     * @return
     */
    public DOSProjectVersionPhaseRelation getVersionPhaseRelation(Integer versionId, Integer phaseType, Integer phaseStatusType, Integer current) {
        DOSProjectVersionPhaseRelation condition = DOSProjectVersionPhaseRelation.builder()
                .versionId(versionId)
                .phaseType(phaseType)
                .phaseStatusType(phaseStatusType)
                .currentFlag(current)
                .build();
        List<DOSProjectVersionPhaseRelation> list = dosProjectVersionPhaseRelationService.getByCondition(condition);
        Assert.isTrue(list.size() == 1 && list.get(0) != null, "数据异常，请检查版本流程相关数据");
        return list.get(0);
    }


    /**
     * @return com.devops.admin.model.DOSProjectVersionOperateLog
     * @Author heyabo
     * @Description 获取审核拒绝的拒绝信息
     * @Date 08:51 2022/6/30
     * @Param [versionId]
     **/
    private DOSProjectVersionOperateLog getOperationLog(Integer versionId) {
        LambdaQueryWrapper<DOSProjectVersionOperateLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DOSProjectVersionOperateLog::getVersionId, versionId)
                .eq(DOSProjectVersionOperateLog::getActionType, DevOpsConstant.ProjectVersionOperateActionType.REVIEW_REJECT)
                .orderByDesc(DOSProjectVersionOperateLog::getCreateTime);
        List<DOSProjectVersionOperateLog> list = dosProjectVersionOperateLogService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }

        return null;
    }

    @Override
    public Publisher<Integer> monitorVersionStatus(Integer versionId, String type) {
        if ("review".equals(type)) {
            // 订阅版本审核状态
            return dealPublisherVersionReviewByVersionId(versionId);
        } else {
            // 订阅版本结束状态
            return dealPublisherVersionEndByVersionId(versionId);
        }
    }

    /**
     * @return org.reactivestreams.Publisher<java.lang.Integer>
     * @Author heyabo
     * @Description 订阅版本结束
     * @Date 09:38 2022/12/2
     * @Param [valueOf]
     **/
    private Publisher<Integer> dealPublisherVersionEndByVersionId(Integer versionId) {

        return Flux.create(emitter -> {
            boolean skipFlag = false;
            int doCount = 0;
            while (!skipFlag && doCount < 12) {
                doCount ++;
                ThreadUtil.sleep(10000L);
                DOSProjectVersionPhaseRelation versionPhaseEnd = dosProjectVersionPhaseRelationService.getOne(Wrappers.<DOSProjectVersionPhaseRelation>lambdaQuery()
                        .eq(DOSProjectVersionPhaseRelation::getVersionId, versionId)
                        .eq(DOSProjectVersionPhaseRelation::getPhaseType, DevOpsConstant.ProjectVersionPhaseType.END));
                if (versionPhaseEnd != null && versionPhaseEnd.getId() != null && versionPhaseEnd.getId() > 0) {
                    if (versionPhaseEnd.getPhaseStatusType().intValue() == DevOpsConstant.ProjectVersionPhaseStatusType.END_FOLLOW) {
                        emitter.next(4);
                        emitter.complete();
                        break;
                    }
                } else {
                    emitter.next(3);
                    emitter.complete();
                    skipFlag = true;
                }
            }
        });
    }

    /**
     * @return org.reactivestreams.Publisher<java.lang.Integer>
     * @Author heyabo
     * @Description 订阅版本审核结果的
     * @Date 09:38 2022/12/2
     * @Param [versionId]
     **/
    public Publisher<Integer> dealPublisherVersionReviewByVersionId(Integer versionId) {
        return Flux.create(emitter -> {
            boolean skipFlag = false;
            int doCount = 0;
            while (!skipFlag && doCount < 180) {
                doCount++;
                ThreadUtil.sleep(10000L);
                DOSProjectVersionPhaseRelation versionPhase = dosProjectVersionPhaseRelationService.getOne(Wrappers.<DOSProjectVersionPhaseRelation>lambdaQuery()
                        .eq(DOSProjectVersionPhaseRelation::getVersionId, versionId)
                        .eq(DOSProjectVersionPhaseRelation::getPhaseType, DevOpsConstant.ProjectVersionPhaseType.QA_REVIEW));
                if (versionPhase != null && versionPhase.getId() != null && versionPhase.getId() > 0) {
                    int phaseStatusType = versionPhase.getPhaseStatusType();
                    if (phaseStatusType == DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_ACCEPT) {
                        emitter.next(1);//审核通过
                        emitter.complete();
                        skipFlag = true;
                    } else if (phaseStatusType == DevOpsConstant.ProjectVersionPhaseStatusType.QA_REVIEW_REJECT) {
                        emitter.next(2);//审核拒绝
                        emitter.complete();
                        skipFlag = true;
                    }
                } else {
                    emitter.next(3);//数据异常
                    emitter.complete();
                    skipFlag = true;
                }
            }
        });
    }

    @Override
    public void checkTimeOutProjectVersion(Integer versionId) {
        WorkflowOptions options = WorkflowOptions.newBuilder()
                .setTaskQueue(DevOpsConstant.PROJECT_VERSION_WORKFLOW_TASK_QUEUE)
                .setWorkflowId(versionId.toString())
                .setWorkflowTaskTimeout(Duration.ofMinutes(1))
                .setWorkflowExecutionTimeout(Duration.ofHours(25))
                .setWorkflowRunTimeout(Duration.ofHours(25))
                .build();
        DOSProjectVersionTimeOutWorkflow workflow = workflowClient.newWorkflowStub(DOSProjectVersionTimeOutWorkflow.class, options);
        workflow.checkTimeOutProjectVersion(versionId);
    }
}
